/*
 * Lucas McDaniel
 * GSoC '11
 * HoneyViz
 * 
 * 
 */

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.JPanel;

public class SphereMetric extends JPanel {
    
    private final int minVal = 3;
    private final double maxRatio = 0.1;
    private final double minPercent = 0.0001;
    
    public SphereMetric()
    {
        Dimension size = new Dimension(350, 350);
        setPreferredSize(size);
        setMinimumSize(size);
        setMaximumSize(size);
        setSize(size);
        setLayout(null);
    }
    
    public ArrayList makeList()
    {
        //EventColorManager.reset();
        ArrayList nameList = EventColorManager.getNameList();
        ArrayList result = new ArrayList();
        ArrayList sLocList = new ArrayList();
        
        if (nameList.size()==0)
            return new ArrayList();
        
        String[] events = new String[nameList.size()];
        String[] storeEvents = events;
        nameList.toArray(events);
        if (AppletState.getPrimarySearch()==0)
            result = HoneyData.groupBy(events, null, null, true, false, false);
        else
        {
            int tmp = AppletState.getPrimarySearch();
            AppletState.setPrimarySearch(0);
            result = HoneyData.groupBy(null, null, LocationManager.getLocations(events), true, false, false);
            AppletState.setPrimarySearch(tmp);
        }
        if (result.size() < 1)
        {
            result = new ArrayList();
            return new ArrayList();
        }
        
        ArrayList interest = new ArrayList();
        interest.add((DataElement)result.get(0));
        for (int inc=1; inc<result.size(); inc++)
        {
            DataElement DE = (DataElement)result.get(inc);
            if (DE.count >= ((DataElement)interest.get(0)).count * minPercent)
            {
                boolean found = false;
                for (int inc2=0; inc2<interest.size(); inc2++)
                    if (DE.count > ((DataElement)interest.get(inc2)).count)
                    {
                        found = true;
                        interest.add(inc2, DE);
                        break;
                    }
                if (!found)
                    interest.add(DE);
            }
        }
        if (interest.size() > result.size() * maxRatio && interest.size()>minVal)
            interest = new ArrayList(interest.subList(0, (int)(result.size() * maxRatio)));
        for (int inc=0; inc<interest.size(); inc++)
        {
            if (((DataElement)interest.get(0)).count * minPercent > ((DataElement)interest.get(inc)).count)
            {
                interest = new ArrayList(interest.subList(0, inc));
                break;
            }
        }
        events = new String[interest.size()];
        for (int inc=0; inc<interest.size(); inc++)
        {
            int index = inc;
            for (int inc2=inc+1; inc2<interest.size(); inc2++)
            {
                if (((DataElement)interest.get(index)).name.compareTo(((DataElement)interest.get(inc2)).name)>0)
                    index = inc2;
            }
            Collections.swap(interest, inc, index);
        }
        for (int inc=0; inc<interest.size(); inc++)
        {
            events[inc] = ((DataElement)interest.get(inc)).name;
        }
        
        if (AppletState.getPrimarySearch()==0)
            result = HoneyData.groupBy(events, null, null, true, false, true);
        else
        {
            int tmp = AppletState.getPrimarySearch();
            AppletState.setPrimarySearch(0);
            result = HoneyData.groupBy(events, null, LocationManager.getSortedLocations(storeEvents), true, false, true);
            AppletState.setPrimarySearch(tmp);
        }
        
        boolean [] arr = new boolean [events.length];
        for (int inc=0; inc<arr.length; inc++)
            arr[inc] = false;
        
        for (int inc=0; inc<result.size(); inc++)
        {
            DataElement DE = (DataElement)result.get(inc);
            for (int inc2=0; inc2<arr.length; inc2++)
            {
                if (DE.name.compareTo(events[inc2])==0)
                    arr[inc2] = true;
            }
        }
        
        for (int inc=0; inc<result.size(); inc++)
        {
            DataElement DE = (DataElement)result.get(inc);
            boolean found = false;
            for (int inc2=0; inc2<sLocList.size(); inc2++)
            {
                int cmpVal = ((SphereLocation)sLocList.get(inc2)).compareTo(DE);
                if (cmpVal==0)
                {
                    ((SphereLocation)sLocList.get(inc2)).add(DE);
                    found = true;
                    break;
                }
                else if (cmpVal > 0)
                {
                    sLocList.add(inc2, new SphereLocation(DE, events));
                    found = true;
                    break;
                }
            }
            if (!found)
                sLocList.add(new SphereLocation(DE, events));
        }
        
        double[][] locList = new double[sLocList.size()][2];
        
        for (int inc=0; inc<sLocList.size(); inc++)
        {
            SphereLocation SL = (SphereLocation)sLocList.get(inc);
            if (EventColorManager.getIndexOf(SL.getName())==-1)
                EventColorManager.add(SL.createEventColorConversion());
            locList[inc][0] = SL.latitude;
            locList[inc][1] = SL.longitude;
        }
        
        ArrayList latVals = new ArrayList();
        ArrayList longVals = new ArrayList();
        
        result = HoneyData.groupBy(null, null, locList, false, false, true);
        
        for (int inc=0; inc<result.size(); inc++)
        {
            DataElement DE = (DataElement)result.get(inc);
            for (int inc2=0; inc2<sLocList.size(); inc2++)
            {
                if (((SphereLocation)sLocList.get(inc2)).compareTo(DE)==0)
                {
                    ((SphereLocation)sLocList.get(inc2)).addMax(DE.count);
                    break;
                }
            }
        }
        
        for (int inc=0; inc<sLocList.size(); inc++)
        {
            SphereLocation SL = (SphereLocation)sLocList.get(inc);
        }
        
        ArrayList eventCons = new ArrayList();
        
        for (int inc=0; inc<sLocList.size(); inc++)
        {
            ((SphereLocation)sLocList.get(inc)).makeLocs();
            eventCons.add(((SphereLocation)sLocList.get(inc)).createDataElementConversion());
        }
        
        if (eventCons == null)
            return new ArrayList();
        else if (eventCons.size()==0)
            return new ArrayList();
        if (EventColorManager.getEvent(((DataElement)eventCons.get(0)).name).paint==null)
            EventColorManager.makeColors(eventCons);
        
        return sLocList;
    }
    
    public void paintComponent(Graphics g)
    {
        boolean tmpDistinct = AppletState.isDistinct();
        AppletState.setDistinct(false);
                
        AppletState.setSizeX(getWidth());
        AppletState.setSizeY(getHeight());
        
        ArrayList nameList = EventColorManager.getNameList();
        ArrayList result = new ArrayList();
        
        if (nameList.size()==0)
            return;
        
        if (AppletState.isInSphereCache(nameList))
        {
            result = AppletState.getSphereCache();
        }
        else
        {
            result = makeList();
            AppletState.makeSphereCache(nameList, result);
        }
        if (result.size()==0)
            return;
        int count = ((SphereLocation)result.get(0)).eventList.length;
        int radius = 0;
        int tmpInc = 0;
        g.setColor(Color.red);
        int size = (int)((getWidth()<getHeight()?getHeight():getWidth())/1.5);
        while (count>=0)
        {
            int y = (int)(Math.cos(6.28*tmpInc/(radius*6))*radius * size / 15) + getHeight()/2 - size / 30;
            int x = (int)(Math.sin(6.28*tmpInc/(radius*6))*radius * size / 15) + getWidth()/2 - size / 30;
            count--;
            tmpInc++;
            if (tmpInc>=radius*6)
            {
                tmpInc=0;
                radius++;
            }
            g.drawOval(x, y, size / 15, size / 15);
        }
        for (int inc=0; inc<result.size(); inc++)
        {
            SphereLocation SL = (SphereLocation)result.get(inc);
            g.setColor(EventColorManager.getEvent(SL.getName()).paint);
            for (int inc2=0; inc2<SL.rtnVals.length; inc2++)
            {
                double x = SL.rtnVals[inc2][0];
                double y = SL.rtnVals[inc2][1];
                
                int xVal = (int)(x*size/15) + getWidth()/2;
                int yVal = (int)(y*size/15) + getHeight()/2;
                
                g.fillOval(xVal, yVal, 5, 5);
            }
        }
        AppletState.setDistinct(tmpDistinct);
        g.setColor(Color.BLUE);
        //g.fillOval(317, 406, 5, 5);
    }
}
